#ifndef CHAIN_CORE_H_
#define CHAIN_CORE_H_

#include "Lock.hh"
#include "Node.hh"

//
/**
 * \file ChainCore.hh
 * \author  jsk <jsk.jinsubkim@gmail.com>
 * \version 1.0
 *
 * \class ChainCore ChainCore.hh
 * \see DoublyNode
 * 
 * Thread safe한 양방향 링크드 리스트(doubly linked list)를 구현한다.
 * 
 * 리스트는 Node 클래스를 이용해서 각 노드를 연결하고, 헤더와 테일이 있어서 
 * 헤더와 테일 모두 입력과 출력이 가능하다. 또한 입력과 출력 모두 락을 통해서 
 * 보호하기 때문에 thread safe하다.
 * 
 * \warning
 * 
 * 리스트 중간에 삽입하는 기능이 아직 구현되지 않았다.
 */
class ChainCore
{
public:
	/**
	 * \name ChainCore 
	 */
	ChainCore(Lock* Key);
	
	/**
	 * \name addHeader
	 * \param Obj 리스트에 추가될 오브젝트.
	 * 
	 * 헤더에 노드를 추가한다.
	 * 
	 * 데이터를 포함하는 노드를 생성하고, 노드를 헤더의 윈쪽에 삽입한다.
	 * 삽입 과정을 거치면 리스트는 아래와 같이 변한다.
	 * 
	 * Before: [Header] --- [Some node] --- [Tail]
	 * After: [New Header] --- [Old Header] --- [Some node] --- [Tail]
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf addHeader(void* Obj);
	
	/**
	 * \name addTail
	 * \param Obj 리스트에 추가될 오브젝트.
	 * 
	 * 테일에 노드를 추가한다.
	 * 
	 * 데이터를 포함하는 노드를 생성하고, 노드를 테일의 오른쪽에 삽입한다.
	 * 삽입 과정을 거치면 리스트는 아래와 같이 변한다.
	 * 
	 * Before: [Header] --- [Some node] --- [Tail]
	 * After: [Header] --- [Some node] --- [Old Tail] --- [New Tail]
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf addTail(void* Obj);
	
	/**
	 * \name clear
	 * 
	 * 모든 노드를 제거한다.
	 * 
	 * 헤더와 테일이 NULL이 될때까지 노드를 제거한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf clear();
	
	/**
	 * \name removeHeader
	 * 
	 * 헤더에 있는 노드를 제거하고 반환한다.
	 * 
	 * 헤더를 헤더의 오른쪽에 있는 노드로 대체하고, 이전 헤더 노드를 가져온다.
	 * 이전 헤더 노드의 데이터를 추출하고, 노드를 제거한다.
	 * 
	 * \return 
	 * 
	 * 헤더에 있는 노드의 데이터, 
	 * 리스트가 비어있을 경우 NULL.
	 */
	virtual void* removeHeader();
	
	/**
	 * \name removeTail
	 * 
	 * 테일에 있는 노드를 제거하고 반환한다.
	 * 
	 * 테일을 테일의 윈쪽 노드로 대체하고, 이전 테일 노드를 가져온다.
	 * 이전 테일 노드의 데이터를 추출하고, 노드를 제거한다.
	 * 
	 * \return 
	 * 
	 * 테일에 있는 노드의 데이터, 
	 * 리스트가 비어있을 경우 NULL.
	 */
	virtual void* removeTail();
	
	/**
	 * \name tellSize
	 * 
	 * 리스트에 포함된 노드의 개수를 알려준다.
	 * 
	 * \return 
	 * 
	 * 노드의 개수.
	 */
	virtual USNumber tellSize();
	
	/**
	 * \name tellSizeWithSync
	 * 
	 * 리스트에 포함된 노드의 개수를 알려준다.
	 * 
	 * 값을 일기전에 동기화를 시도한다. 보다 정확한 수치를 읽을 수 있다.
	 * Queue 클래스는 Chain 클래스를 이용하는데, Queue 클래스의 flush 메소드를
	 * 사용하는 부분에서 동기화 없이 큐의 크기를 읽기 때문에 잘 못된 행동을 방지하기
	 * 위해서 특별한 인터페이스를 제공한다.
	 * 
	 * \return 
	 * 
	 * 노드의 개수.
	 */
	virtual USNumber tellSizeWithSync();
	
	// Node
protected:
	/**
	 * \name createNode
	 * \param Obj 노드의 데이터.
	 * 
	 * 노드를 생성한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual Node* createNode(void* Obj);
	
	/**
	 * \name replaceHeader
	 * \param NewNode 새로운 노드.
	 * 
	 * 헤더와 새로운 노드를 연결하고, 헤더를 변경한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf replaceHeader(Node* NewNode);
	
	/**
	 * \name replaceTail
	 * \param NewNode 새로운 노드.
	 * 
	 * 테일과 새로운 노드를 연결하고, 테일를 변경한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf replaceTail(Node* NewNode);
	
	/**
	 * \name updateHeader
	 * 
	 * 헤더를 갱신한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf updateHeader();
	
	/**
	 * \name updateTail
	 * 
	 * 테일를 갱신한다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf updateTail();
	
	// Member
protected:
	/**
	 * 리스트 삽입/삭제를 보호하는 락.
	 */
	Lock* LockOfIO;
	
	/**
	 * 리스트의 시작을 가르키는 포인터.
	 */
	Node* Header;
	
	/**
	 * 리스트의 끝을 가르키는 포인터.
	 */
	Node* Tail;
	
	/**
	 * 리스트에 연결된 노드의 개수.
	 */
	USNumber NumOfNode;
	
	/**
	 * 인스턴스의 상태를 나타낸다.
	 * TRUE일 경우 정상, FALSE일 경우 비정상.
	 */
	bool State;
};

#endif //CHAIN_CORE_H_